-use std::collections::{HashMap, HashSet};
-use std::collections::hashmap::{Occupied, Vacant};
+use std::collections::hashmap::{HashMap, HashSet, Occupied, Vacant};
use std::fmt;
use semver;
None => return Err(human(format!("package id specification `{}` \
matched no packages", spec))),
};
- match ids.next() {
+ return match ids.next() {
Some(other) => {
- let mut msg = format!("Ambiguous package id specification: \
- `{}`\nMatching packages:\n {}\n {}",
- spec, ret, other);
- for id in ids {
- msg = format!("{}\n {}", msg, id);
- }
+ let mut msg = format!("There are multiple `{}` packages in \
+ your project, and the specification \
+ `{}` is ambiguous.\n\
+ Please re-run this command \
+ with `-p <spec>` where `<spec>` is one \
+ of the following:",
+ spec.get_name(), spec);
+ let mut vec = vec![ret, other];
+ vec.extend(ids);
+ minimize(&mut msg, vec, &spec);
Err(human(msg))
}
None => Ok(ret)
+ };
+
+ fn minimize(msg: &mut String,
+ ids: Vec<&PackageId>,
+ spec: &PackageIdSpec) {
+ let mut version_cnt = HashMap::new();
+ for id in ids.iter() {
+ let slot = match version_cnt.entry(id.get_version()) {
+ Occupied(e) => e.into_mut(),
+ Vacant(e) => e.set(0u),
+ };
+ *slot += 1;
+ }
+ for id in ids.iter() {
+ if version_cnt[id.get_version()] == 1 {
+ msg.push_str(format!("\n {}:{}", spec.get_name(),
+ id.get_version()).as_slice());
+ } else {
+ msg.push_str(format!("\n {}",
+ PackageIdSpec::from_package_id(*id))
+ .as_slice());
+ }
+ }
}
}
COMPILING, p.url()))
.with_stderr(""));
})
+
+test!(update_ambiguous {
+ let foo1 = git_repo("foo1", |project| {
+ project.file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("src/lib.rs", "")
+ }).assert();
+ let foo2 = git_repo("foo2", |project| {
+ project.file("Cargo.toml", r#"
+ [package]
+ name = "foo"
+ version = "0.6.0"
+ authors = ["wycats@example.com"]
+ "#)
+ .file("src/lib.rs", "")
+ }).assert();
+ let bar = git_repo("bar", |project| {
+ project.file("Cargo.toml", format!(r#"
+ [package]
+ name = "bar"
+ version = "0.5.0"
+ authors = ["wycats@example.com"]
+
+ [dependencies.foo]
+ git = '{}'
+ "#, foo2.url()).as_slice())
+ .file("src/lib.rs", "")
+ }).assert();
+
+ let p = project("project")
+ .file("Cargo.toml", format!(r#"
+ [project]
+ name = "project"
+ version = "0.5.0"
+ authors = []
+ [dependencies.foo]
+ git = '{}'
+ [dependencies.bar]
+ git = '{}'
+ "#, foo1.url(), bar.url()).as_slice())
+ .file("src/main.rs", "fn main() {}");
+
+ assert_that(p.cargo_process("generate-lockfile"), execs().with_status(0));
+ assert_that(p.process(cargo_dir().join("cargo")).arg("update")
+ .arg("-p").arg("foo"),
+ execs().with_status(101)
+ .with_stderr("\
+There are multiple `foo` packages in your project, and the specification `foo` \
+is ambiguous.
+Please re-run this command with `-p <spec>` where `<spec>` is one of the \
+following:
+ foo:0.[..].0
+ foo:0.[..].0
+"));
+})